﻿//--------------------------------------------------------------------------------------------------------------------------------------------------------
// <copyright file="RegistrationService.cs">
//     Copyright © 2010 Oli Francis
//     This source code is subject to the terms and conditions of the MIT license. A copy of the license can be found in the license.txt 
//     file at the root of this distribution. By using this source code in any fashion, you are agreeing to be bound by the terms of the MIT License. 
//     You must not remove this notice from the software.
// </copyright>
// <author>Oli</author>
//-------------------------------------------------------------------------------------------------------------------------------------------------------

namespace TeamBrain.Domain.Services.Registration
{
    #region Using Statements

    using System;

    using TeamBrain.Domain.Core;
    using TeamBrain.Domain.Core.Repositories;
    using TeamBrain.Domain.Model;
    using TeamBrain.Domain.Services.Email;
    using TeamBrain.Domain.Services.Exceptions;
    using TeamBrain.Domain.Services.Security;

    #endregion

    /// <summary>
    /// Exposes application services around registering users
    /// </summary>
    public class RegistrationService : IRegistrationService
    {
        private readonly IUserRepository userRepository;
        private readonly IEmailService emailService;
        private readonly IPasswordHasher passwordHasher;
        private readonly IUnitOfWork unitOfWork;
        private readonly ISecurityService securityService;

        /// <summary>
        /// Initializes a new instance of the <see cref="RegistrationService"/> class.
        /// </summary>
        public RegistrationService(
            IUnitOfWork unitOfWork,
            IUserRepository userRepository,
            IEmailService emailService,
            IPasswordHasher passwordHasher,
            ISecurityService securityService)
        {
            this.userRepository = userRepository;
            this.emailService = emailService;
            this.passwordHasher = passwordHasher;
            this.securityService = securityService;
            this.unitOfWork = unitOfWork;
        }

        /// <summary>
        /// Registers a new user and sends them an email to ensure they have entered a valid address
        /// they are authorised to use
        /// </summary>
        public void RegisterNewUser(User user)
        {
            var existingUser = this.userRepository.GetByEmailAddress(user.EmailAddress);

            if (existingUser != null)
            {
                throw new EmailAlreadyRegisteredException();
            }

            this.emailService.SendUserActivationEmail(user);

            user.IsActive = false;
            user.ActivationToken = Guid.NewGuid().ToString();
            user.Salt = this.passwordHasher.GetNewSalt();
            user.PasswordHash = this.passwordHasher.GetPasswordHash(user.Salt, user.Password);
            user.Password = null;

            this.userRepository.Add(user);
            this.unitOfWork.Flush();
        }

        /// <summary>
        /// Verifies a user account based on a given token from the verification email
        /// </summary>
        public void ActivateUserFromToken(string token)
        {
            var user = this.userRepository.GetByActivationToken(token);

            if (user == null)
            {
                throw new InvalidActivationTokenException();
            }

            if (user.IsActive == false)
            {
                user.IsActive = true;
                user.ActivationToken = null;
                this.unitOfWork.Flush();

                this.securityService.SignInActivatedUser(user.Id);
            }
        }
    }
}